package sharemem

import (
	"server_cluster/common/tools"
    "server_cluster/common/protoc/pb"
	"server_cluster/common/logger"
    "server_cluster/battle/battle_config"
)

const (
	UNIT_TYPE_MONSTER			= 1		// 怪物
	UNIT_TYPE_ROLE				= 2		// 上场角色
	UNIT_TYPE_ROLE_ASSIST		= 3		// 支援角色

	UNIT_ATTR_MAX				= 64	// 单位属性上限
	UNIT_NORMAL_CARD_MAX		= 2		// 单位普通技能上限
	UNIT_PASSIVE_MAX			= 16	// 单位被动上限
	UNIT_ORDERS_MAX				= 10	// 单位序列上限
	UNIT_WEAK_MAX				= 8		// 单位弱点上限
	UNIT_CFG_EFFECT_MAX			= 10	// 单位可养成效果数量上限
	UNIT_CFG_EFFECT_PARAM_MAX	= 40	// 单位可养成效果数量上限
	UNIT_STATE_MAX				= 8		// 单位拥有状态上限(动态管理可突破)
	UNIT_BUFF_MAX				= 20	// 单位拥有buff上限(动态管理可突破)
)

type Attr struct {
	Id		int32
	Val_init int32 // 初始值
	Val      int32 // 当前值
}

func (a *Attr) meminit() {
	a.Id = 0
	a.Val = 0
	a.Val_init = 0
}

type Id_time struct {
	Id   int32
	Time int32
}

func (t *Id_time) meminit() {
	t.Id = 0
	t.Time = 0
}

type CfgEffectParamUpdate struct {
	id				int32
	param1			[BATTLE_PARAM_MAX1][BATTLE_PARAM_MAX2]int32
	param2			[BATTLE_PARAM_MAX1][BATTLE_PARAM_MAX2]int32
	param3			int32
	param4			int32
	param5			int32
	param6			[BATTLE_PARAM_MAX1]int32
}

func (s *CfgEffectParamUpdate)meminit() {
	var i,j int8
	s.id = 0
	for i=0;i<BATTLE_PARAM_MAX1;i++ {
		for j=0;j<BATTLE_PARAM_MAX2;j++ {
			s.param1[i][j] = 0
		}
	}
	for i=0;i<BATTLE_PARAM_MAX1;i++ {
		for j=0;j<BATTLE_PARAM_MAX2;j++ {
			s.param2[i][j] = 0
		}
	}
	s.param3 = 0
	s.param4 = 0
	s.param5 = 0
	for i=0;i<BATTLE_PARAM_MAX1;i++ {
		s.param6[i] = 0
	}
}

type CfgEffectUpdate struct {
	id			int32
	effect		[SKILL_CHILD_EFFECT_MAX]int32
}

func (s *CfgEffectUpdate)meminit() {
	var i int8
	s.id = 0
	for i=0;i<SKILL_CHILD_EFFECT_MAX;i++ {
		s.effect[i] = 0
	}
}

type ShmUnit struct {
	id						int32
	index					int8						//单位数组下标
	Type					int8						//单位类型(1 怪物 2 上阵角色 3 支援角色)
	tag						int8						//tag
	weak					[UNIT_WEAK_MAX]int8			//弱点
	ex_card					int32						//大招
	card_id					[UNIT_NORMAL_CARD_MAX]int32	//普技
	order					[UNIT_ORDERS_MAX]Id_time	//序列攻击
	at						[UNIT_ATTR_MAX]Attr
	passive					[UNIT_PASSIVE_MAX]int32
	cfg_effect_update		[UNIT_CFG_EFFECT_MAX]CfgEffectUpdate
	cfg_effect_param_update	[UNIT_CFG_EFFECT_PARAM_MAX]CfgEffectParamUpdate
}

func (r *ShmUnit) meminit(index int8) {
	var i int8
	r.id = 0
	r.index = index
	r.Type = 0
	r.tag = 0
	r.ex_card = 0
	for i = 0; i < UNIT_NORMAL_CARD_MAX; i++ {
		r.card_id[i] = 0
	}
	for i = 0; i < UNIT_ATTR_MAX; i++ {
		r.at[i].meminit()
	}
	for i = 0; i < UNIT_PASSIVE_MAX; i++ {
		r.passive[i] = 0
	}
	for i = 0; i < UNIT_ORDERS_MAX; i++ {
		r.order[i].meminit()
	}
	for i = 0; i < UNIT_WEAK_MAX; i++ {
		r.weak[i] = 0
	}
	for i = 0; i< UNIT_CFG_EFFECT_MAX; i++ {
		r.cfg_effect_update[i].meminit()
	}
	for i = 0; i< UNIT_CFG_EFFECT_PARAM_MAX; i++ {
		r.cfg_effect_param_update[i].meminit()
	}
}
//

func (u *ShmUnit) BuildByPb(Type int8,base *pb.BaseInfo) bool {
	// id
	u.id = base.Id
	u.Type = Type
	u.tag = int8(base.RoleTag)
	// ex_card
	u.ex_card = base.ExCard
	// cards
	if len(base.CardId) != UNIT_NORMAL_CARD_MAX {
		logger.Error("len card != UNIT_NORMAL_CARD_MAX:%d",len(base.CardId))
		return false
	}
	for k2, v2 := range base.CardId {
		u.card_id[k2] = v2
	}
	// attr
	if len(base.Attr) > UNIT_ATTR_MAX {
		logger.Error("len attr > UNIT_ATTR_MAX:%d",len(base.Attr))
		return false
	}
	// logger.Info("attr = %v",v.Attr)
	for k2, v2 := range base.Attr {
		u.at[k2].Id = v2.Id
		u.at[k2].Val = v2.Val
	}
	//
	// skill-passive
	if len(base.Passive) > UNIT_PASSIVE_MAX {
		logger.Error("len passive > UNIT_PASSIVE_MAX:%d",len(base.Passive))
		return false
	}
	for k2, v2 := range base.Passive {
		u.passive[k2] = v2
	}
	// order
	if len(base.Attack) > UNIT_ORDERS_MAX {
		logger.Error("len attack > UNIT_ORDERS_MAX:%d",len(base.Attack))
		return false
	}
	for k2, v2 := range base.Attack {
		u.order[k2].Id = v2.Card
		u.order[k2].Time = v2.CdTime
	}
	if len(base.CfgEffect) > UNIT_CFG_EFFECT_MAX {
		logger.Error("len cfg effect > UNIT_CFG_EFFECT_MAX:%d",len(base.CfgEffect))
		return false
	}
	for k2,v2 := range base.CfgEffect {
		u.cfg_effect_update[k2].id = v2.Id
		if len(v2.SkillEffect) > SKILL_CHILD_EFFECT_MAX{
			logger.Error("len skill effect > SKILL_CHILD_EFFECT_MAX:%d",len(v2.SkillEffect))
			return false
		}
		for k3,v3 := range v2.SkillEffect {
			u.cfg_effect_update[k2].effect[k3] = v3
		}
	}
	if len(base.CfgEffectParam) > UNIT_CFG_EFFECT_PARAM_MAX {
		logger.Error("len cfg effect param > UNIT_CFG_EFFECT_PARAM_MAX:%d",len(base.CfgEffectParam))
		return false
	}
	for k2,v2 := range base.CfgEffectParam {
		u.cfg_effect_param_update[k2].id = v2.Id
		if len(v2.Param1) > BATTLE_PARAM_MAX1 {
			logger.Error("len v2 Param1 > BATTLE_PARAM_MAX1:%d",len(v2.Param1))
			return false
		}
		for k3,v3 := range v2.Param1 {
			if len(v3.Value) > BATTLE_PARAM_MAX2 {
				logger.Error("len v3 Value > BATTLE_PARAM_MAX2:%d",len(v3.Value))
				return false
			}
			for k4,v4 := range v3.Value {
				u.cfg_effect_param_update[k2].param1[k3][k4] = v4
			}
		}
		if len(v2.Param2) > BATTLE_PARAM_MAX1 {
			logger.Error("len v2 Param2 > BATTLE_PARAM_MAX1:%d",len(v2.Param2))
			return false
		}
		for k3,v3 := range v2.Param2 {
			if len(v3.Value) > BATTLE_PARAM_MAX2 {
				logger.Error("len v3 Value > BATTLE_PARAM_MAX2:%d",len(v3.Value))
				return false
			}
			for k4,v4 := range v3.Value {
				u.cfg_effect_param_update[k2].param2[k3][k4] = v4
			}
		}
		u.cfg_effect_param_update[k2].param3 = v2.Param3
		u.cfg_effect_param_update[k2].param4 = v2.Param4
		u.cfg_effect_param_update[k2].param5 = v2.Param5
		if len(v2.Param6) > BATTLE_PARAM_MAX1 {
			logger.Error("len v2 Param6 > BATTLE_PARAM_MAX1:%d",len(v2.Param6))
			return false
		}
		for k3,v3 := range v2.Param6 {
			u.cfg_effect_param_update[k2].param6[k3] = v3
		}
	}
	return true
}

func (u *ShmUnit)BuildMonster(cfg *Monster) bool {
	var j int8
	// id
	u.id = cfg.Id
	u.Type = UNIT_TYPE_MONSTER
	u.ex_card = cfg.Ex_skill
	// attr
	cfg_attr := Get_config_monster_attr(cfg.Attr)
	if cfg_attr == nil {
		logger.Error("cfg_attr nil %d", cfg.Attr)
		return false
	}
	for j = 0; j < UNIT_ATTR_MAX; j++ {
		if cfg_attr.At[j].Id <= 0 {
			break
		}
		u.at[j].Id = cfg_attr.At[j].Id
		u.at[j].Val = cfg_attr.At[j].Val
	}
	// passive
	for j = 0; j < UNIT_PASSIVE_MAX; j++ {
		if cfg.Passive[j] <= 0 {
			break
		}
		u.passive[j] = cfg.Passive[j]
	}
	// attack
	for j = 0; j < UNIT_ORDERS_MAX; j++ {
		if cfg.Order[j].Id <= 0 {
			break
		}
		u.order[j].Id = cfg.Order[j].Id
		u.order[j].Time = cfg.Order[j].Time
	}
	// weak_point
	for j = 0; j < UNIT_WEAK_MAX; j++ {
		if cfg.Weak_point[j] <= 0 {
			break
		}
		u.weak[j] = cfg.Weak_point[j]
	}
	u.tag = cfg.Type
	return true
}

func (fu *ShmUnit) Build(area *Battle_area) *Battle_unit {
    if fu.id == 0 {
        //此位置没有单位
        return nil
    }
	bu := &Battle_unit{
		id:fu.id,
		area:area,
		index:fu.index,
		Type:fu.Type,
		tag:fu.tag,

		tough_time:0,
		order_index:0,
		stop_time:-1,
	}
    var i int8
    //弱点
    for i=0;i<UNIT_WEAK_MAX;i++ {
        if fu.weak[i] == 0 {
            break
        }
        bu.weak = append(bu.weak,fu.weak[i])
    }
    //大招
    tmp_card := fu.BuildCfgSkillCard(fu.ex_card)
    if tmp_card == nil && fu.Type == UNIT_TYPE_ROLE {
		logger.Error("build cfg ex_card %d error.",fu.ex_card)
        return nil
    }
    bu.ex_card = tmp_card
    //普通卡牌
    for i=0;i<UNIT_NORMAL_CARD_MAX;i++ {
        if fu.card_id[i] == 0 {
            break
        }
        tmp_card := fu.BuildCfgSkillCard(fu.card_id[i])
        if tmp_card == nil {
			logger.Error("build cfg card %d error.",fu.card_id[i])
            return nil
        }
        bu.GetNormalCardMap()[fu.card_id[i]] = tmp_card
		card_w := &Card_weight {
			id:fu.card_id[i],
			weight:tmp_card.weight,
		}
		bu.card_weight = append(bu.card_weight,card_w)
    }
    //序列
    for i=0;i<UNIT_ORDERS_MAX;i++ {
        if fu.order[i].Id == 0 {
            break
        }
        tmp_card := fu.BuildCfgSkillCard(fu.order[i].Id)
        if tmp_card == nil {
			logger.Error("build cfg order %d error.",fu.order[i].Id)
            return nil
        }
        bu.order = append (bu.order,&Cfg_order{
            skill_card:tmp_card,
            time:fu.order[i].Time,
        })
    }

    bu.order_max = int8(len(bu.order))
	if bu.order_max > 0 {
		bu.order_time = area.root_time + bu.order[bu.order_index].time
	} else {
		logger.Error("unit id%d Type%d tag:%d order_max %d !!!!!!!!!!!!!!!!!",bu.id,bu.Type,bu.tag,bu.order_max)
	}
    //属性
    attr := bu.GetAtMap()
    for i=0;i<UNIT_ATTR_MAX;i++ {
        if fu.at[i].Id == 0 {
            break
        }
		if fu.at[i].Id == HP_REAL || fu.at[i].Id == TOUGH_REAL {
			//暂不需要
			continue
		}
        if attr[fu.at[i].Id] == nil {
            attr[fu.at[i].Id] = &Unit_attr {
                id:fu.at[i].Id,
                val_buff:0,
                val:0,
                val_max:0,
                val_init:0,
            }
        }
		attr[fu.at[i].Id].val = fu.at[i].Val
		attr[fu.at[i].Id].val_max = fu.at[i].Val
		attr[fu.at[i].Id].val_init = fu.at[i].Val
    }
	//继承怒气
	if attr[ANGER] != nil {
		attr[ANGER].val = 0
		if attr[ANGER_REAL] != nil {
			attr[ANGER].val = attr[ANGER_REAL].val
		}
	}
	//初始化冰点值
	freeze := tools.String2Array(battle_config.FREEZE,"|")
	if len(freeze) != 2 {
		logger.Error("attr freezevalue config error.")
		return nil
	}
	attr[FREEZEVALUE] = &Unit_attr {
		id:FREEZEVALUE,
		val_buff:0,
		val:0,
		val_max:freeze[0],
		val_init:freeze[1],
	}
    //被动 init
    for i=0;i<UNIT_PASSIVE_MAX;i++ {
        if fu.passive[i] <= 0 {
            break
        }
        tmp_passive,pos := fu.BuildCfgSkillPassive(fu.passive[i])
        if tmp_passive == nil {
			logger.Error("passive %d is not found.",fu.passive[i])
            return nil
        }
		bu.run_passive = append(bu.run_passive,tmp_passive)
        group := bu.GetPassiveMap(pos)
        *group = append(*group,tmp_passive)
    }
    //
    //test begin
    //bu.ChangeAttr(VAL,HP,bu.TakeAtVal(VAL_MAX,HP))
    //test end
	/*
	for k,v := range attr {
		log.Printf("attr %d = %v",k,v)
	}*/
    return bu
}




